package com.meteor.user.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.meteor.api.feign.newFeign.NewFeign;
import com.meteor.api.feign.newFeign.dto.CommunityDTO;
import com.meteor.api.feign.system.dto.SysMerchantDTO;
import com.meteor.framework.common.base.ResponseData;
import com.meteor.framework.common.cache.RedisCache;
import com.meteor.user.entity.SysUser;
import lombok.AllArgsConstructor;
import com.meteor.api.module.message.SmsApi;
import com.meteor.framework.common.constant.Constant;
import com.meteor.framework.common.exception.ServerException;
import com.meteor.framework.security.cache.TokenStoreCache;
import com.meteor.framework.security.mobile.MobileAuthenticationToken;
import com.meteor.framework.security.user.UserDetail;
import com.meteor.user.enums.LoginOperationEnum;
import com.meteor.user.service.*;
import com.meteor.user.vo.*;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 权限认证服务
 *
 * @author lynn
 * @date 2024/1/03
 */
@Service
@AllArgsConstructor
public class SysAuthServiceImpl implements SysAuthService {
    private final SysCaptchaService sysCaptchaService;
    private final TokenStoreCache tokenStoreCache;
    private final AuthenticationManager authenticationManager;
    private final SysLogLoginService sysLogLoginService;
    private final SysUserService sysUserService;
    private final SysUserTokenService sysUserTokenService;
    private final SmsApi smsApi;
    private final PasswordEncoder passwordEncoder;
    private final RedisCache redisCache;
    private final NewFeign newFeign;

    @Override
    @Transactional
    public SysUserTokenVO loginByAccount(SysAccountLoginVO login) {
        // 验证码效验
        boolean flag = sysCaptchaService.validate(login.getKey(), login.getCaptcha());
        if (!flag) {
            // 保存登录日志
            sysLogLoginService.save(login.getUsername(), Constant.FAIL, LoginOperationEnum.CAPTCHA_FAIL.getValue());

            throw new ServerException("验证码错误");
        }

        //移动端用户判断是否注册
        if(!ObjectUtils.isEmpty(login.getType())&&login.getType().equals(2)){

            ResponseData responseData = JSON.parseObject(newFeign.getCommunity(login.getCommunityId()),ResponseData.class);
            if(!ObjectUtils.isEmpty(responseData.getData())){
                CommunityDTO communityDTO = JSON.parseObject(responseData.getData().toString(),CommunityDTO.class);
                login.setOrgId(communityDTO.getOrgId());
            }

            redisCache.setExpire("login+"+login.getUsername()+":",login.getCommunityId(),4);

            LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysUser::getUsername,login.getUsername());
            wrapper.eq(SysUser::getCommunityId,login.getCommunityId());
            wrapper.eq(SysUser::getDeleted,0);
            wrapper.eq(SysUser::getOrgId,login.getOrgId());
            SysUser sysUser = sysUserService.getOne(wrapper);
            if(ObjectUtils.isEmpty(sysUser)){
                SysUserVO sysUserVO = new SysUserVO();
                sysUserVO.setUsername(login.getUsername());
                sysUserVO.setPassword(passwordEncoder.encode(login.getPassword()));
                sysUserVO.setMobile(login.getUsername());
                sysUserVO.setUserType(2);
                sysUserVO.setStatus(1);
                sysUserVO.setCommunityId(login.getCommunityId());
                sysUserVO.setOrgId(login.getOrgId());
                sysUserVO.setCardStatus(2);
                sysUserService.save(sysUserVO);
            }
        }

        Authentication authentication;
        try {
            // 用户认证
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(login.getUsername(), login.getPassword()));
        } catch (BadCredentialsException e) {
            throw new ServerException("用户名或密码错误");
        }

        // 用户信息
        UserDetail user = (UserDetail) authentication.getPrincipal();

        // 生成 accessToken
        SysUserTokenVO userTokenVO = sysUserTokenService.createToken(user.getId());

        // 保存用户信息到缓存
        tokenStoreCache.saveUser(userTokenVO.getAccessToken(), user);

        return userTokenVO;
    }

    @Override
    @Transactional
    public SysUserTokenVO loginByMobile(SysMobileLoginVO login) {
        Authentication authentication;
        try {

            //移动端用户判断是否注册
            if(!ObjectUtils.isEmpty(login.getType())&&login.getType().equals(2)){

                ResponseData responseData = JSON.parseObject(newFeign.getCommunity(login.getCommunityId()),ResponseData.class);
                if(!ObjectUtils.isEmpty(responseData.getData())){
                    CommunityDTO communityDTO = JSON.parseObject(responseData.getData().toString(),CommunityDTO.class);
                    login.setOrgId(communityDTO.getOrgId());
                }

                redisCache.setExpire("login+"+login.getMobile()+":",login.getCommunityId(),4);

                LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SysUser::getUsername,login.getMobile());
                wrapper.eq(SysUser::getCommunityId,login.getCommunityId());
                wrapper.eq(SysUser::getDeleted,0);
                wrapper.eq(SysUser::getOrgId,login.getOrgId());
                SysUser sysUser = sysUserService.getOne(wrapper);
                if(ObjectUtils.isEmpty(sysUser)){
                    SysUserVO sysUserVO = new SysUserVO();
                    sysUserVO.setUsername(login.getMobile());
                    sysUserVO.setPassword(passwordEncoder.encode("888888"));
                    sysUserVO.setMobile(login.getMobile());
                    sysUserVO.setUserType(2);
                    sysUserVO.setStatus(1);
                    sysUserVO.setCommunityId(login.getCommunityId());
                    sysUserVO.setOrgId(login.getOrgId());
                    sysUserVO.setCardStatus(2);
                    sysUserService.save(sysUserVO);
                }
            }

            // 用户认证
            authentication = authenticationManager.authenticate(
                    new MobileAuthenticationToken(login.getMobile(), login.getCode(),login.getCommunityId()));
        } catch (BadCredentialsException e) {
            throw new ServerException("手机号或验证码错误");
        }

        // 用户信息
        UserDetail user = (UserDetail) authentication.getPrincipal();

        // 生成 accessToken
        SysUserTokenVO userTokenVO = sysUserTokenService.createToken(user.getId());

        // 保存用户信息到缓存
        tokenStoreCache.saveUser(userTokenVO.getAccessToken(), user);

        return userTokenVO;
    }

    @Override
    @Transactional
    public boolean sendCode(String mobile,String communityId,Integer sendType) {
        // 生成6位验证码
        String code = RandomUtil.randomNumbers(6);

        if(ObjectUtils.isEmpty(sendType)||sendType.equals(2)) {
            SysUserVO user = sysUserService.getByMobile(mobile, communityId);
            if (user == null) {
                throw new ServerException("手机号未注册");
            }
        }
        redisCache.expire("sms:" +communityId + ":"+ mobile,60);

        // 发送短信
        return smsApi.sendCode(mobile, "code", code);
    }

    @Override
    public AccessTokenVO getAccessToken(String refreshToken) {
        SysUserTokenVO token = sysUserTokenService.refreshToken(refreshToken);

        // 封装 AccessToken
        AccessTokenVO accessToken = new AccessTokenVO();
        accessToken.setAccessToken(token.getAccessToken());
        accessToken.setAccessTokenExpire(token.getAccessTokenExpire());

        return accessToken;
    }

    @Override
    public void logout(String accessToken) {
        // 用户信息
        UserDetail user = tokenStoreCache.getUser(accessToken);

        // 删除用户信息
        tokenStoreCache.deleteUser(accessToken);

        // Token过期
        sysUserTokenService.expireToken(user.getId());

        // 保存登录日志
        sysLogLoginService.save(user.getUsername(), Constant.SUCCESS, LoginOperationEnum.LOGOUT_SUCCESS.getValue());
    }
}
